set(LLVM_LINK_COMPONENTS
  Option
  FrontendOpenMP
  Support
  TargetParser
  )

add_subdirectory(Core)
add_subdirectory(Inclusions)
add_subdirectory(Refactoring)
add_subdirectory(ASTDiff)
add_subdirectory(DumpTool)
add_subdirectory(Syntax)
add_subdirectory(DependencyScanning)
add_subdirectory(Transformer)

# Replace the last lib component of the current binary directory with include
string(FIND ${CMAKE_CURRENT_BINARY_DIR} "/lib/" PATH_LIB_START REVERSE)
if(PATH_LIB_START EQUAL -1)
  message(FATAL_ERROR "Couldn't find lib component in binary directory")
endif()
math(EXPR PATH_LIB_END "${PATH_LIB_START}+5")
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD)
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} ${PATH_LIB_END} -1 PATH_TAIL)
string(CONCAT BINARY_INCLUDE_DIR ${PATH_HEAD} "/include/clang/" ${PATH_TAIL})

if (NOT Python3_EXECUTABLE
    OR APPLE
    OR CMAKE_CROSSCOMPILING
    OR GENERATOR_IS_MULTI_CONFIG
    OR NOT LLVM_NATIVE_ARCH IN_LIST LLVM_TARGETS_TO_BUILD
    )
    configure_file(
      EmptyNodeIntrospection.inc.in
      ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc
      COPYONLY
    )
    set(CLANG_TOOLING_BUILD_AST_INTROSPECTION "OFF" CACHE BOOL "")
else()
  # The generation of ASTNodeAPI.json takes a long time in a
  # Debug build due to parsing AST.h. Disable the processing
  # but setting CLANG_TOOLING_BUILD_AST_INTROSPECTION as an
  # internal hidden setting to override.
  # When the processing is disabled, a trivial/empty JSON
  # file is generated by clang-ast-dump and generate_cxx_src_locs.py
  # generates the same API, but with a trivial implementation.
  option(CLANG_TOOLING_BUILD_AST_INTROSPECTION "Enable AST introspection" TRUE)

  set(skip_expensive_processing $<OR:$<CONFIG:Debug>,$<NOT:$<BOOL:${CLANG_TOOLING_BUILD_AST_INTROSPECTION}>>>)

  set(implicitDirs)
  foreach(implicitDir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
    list(APPEND implicitDirs -I ${implicitDir})
  endforeach()

  include(GetClangResourceDir)
  get_clang_resource_dir(resource_dir PREFIX ${LLVM_BINARY_DIR})
  add_custom_command(
      COMMENT Generate ASTNodeAPI.json
      OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json
      DEPENDS clang-ast-dump clang-resource-headers
      COMMAND
      $<TARGET_FILE:clang-ast-dump>
        # Skip this in debug mode because parsing AST.h is too slow
        --skip-processing=${skip_expensive_processing}
        -I ${resource_dir}/include
        -I ${CLANG_SOURCE_DIR}/include
        -I ${LLVM_BINARY_DIR}/tools/clang/include
        -I ${LLVM_BINARY_DIR}/include
        -I ${LLVM_SOURCE_DIR}/include
        ${implicitDirs}
        --json-output-path ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json
  )

  add_custom_target(run-ast-api-dump-tool
      DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json
  )

  add_custom_command(
      COMMENT Generate NodeIntrospection.inc
      OUTPUT ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc
      DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json
        ${CMAKE_CURRENT_SOURCE_DIR}/DumpTool/generate_cxx_src_locs.py
        ${CMAKE_CURRENT_SOURCE_DIR}/EmptyNodeIntrospection.inc.in
      COMMAND
      ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/DumpTool/generate_cxx_src_locs.py
        --json-input-path ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json
        --output-file NodeIntrospection.inc
        --use-empty-implementation ${skip_expensive_processing}
        --empty-implementation
          "${CMAKE_CURRENT_SOURCE_DIR}/EmptyNodeIntrospection.inc.in"
      COMMAND
      ${CMAKE_COMMAND} -E copy_if_different
        ${CMAKE_CURRENT_BINARY_DIR}/NodeIntrospection.inc
        ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc
  )

  add_custom_target(run-ast-api-generate-tool
      DEPENDS
      ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc
  )
endif()

add_clang_library(clangTooling
  AllTUsExecution.cpp
  ArgumentsAdjusters.cpp
  CommonOptionsParser.cpp
  CompilationDatabase.cpp
  Execution.cpp
  ExpandResponseFilesCompilationDatabase.cpp
  FileMatchTrie.cpp
  FixIt.cpp
  GuessTargetAndModeCompilationDatabase.cpp
  InterpolatingCompilationDatabase.cpp
  JSONCompilationDatabase.cpp
  Refactoring.cpp
  RefactoringCallbacks.cpp
  StandaloneExecution.cpp
  NodeIntrospection.cpp
  ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc
  Tooling.cpp

  DEPENDS
  ClangDriverOptions
  omp_gen

  LINK_LIBS
  clangAST
  clangASTMatchers
  clangBasic
  clangDriver
  clangFormat
  clangFrontend
  clangLex
  clangRewrite
  clangSerialization
  clangToolingCore
  )
